﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using FikriKibar.Business.Abstract;
using FikriKibar.Common.Entities;
using FikriKibar.Common.Exceptions;
using FikriKibar.Common.Helpers;
using FikriKibar.Common.Validation.FluentValidation.Role;
using FikriKibar.DataAccess;
using FikriKibar.DataAccess.Abstract;
using FikriKibar.Entities.Abstract;
using FikriKibar.Entities.Composite.BaseModels;
using FikriKibar.Entities.Concrete;
using FikriKibar.Globalization;

namespace FikriKibar.Business.Concrete
{
    public class RoleManager : IRoleService
    {
        #region Global Declarations

        private readonly IRoleDal _roleDal = new EfRoleDal();

        private readonly IRoleLanguageLineDal _roleLanguageLineDal = new EfRoleLanguageLineDal();

        private readonly IRoleLanguageLineHistoryDal _roleLanguageLineHistoryDal = new EfRoleLanguageLineHistoryDal();

        private readonly IRoleHistoryDal _roleHistoryDal = new EfRoleHistoryDal();

        private readonly IUserGroupUserLineDal _userGroupUserLineDal = new EfUserGroupUserLineDal();

        private readonly IUserGroupRoleLineDal _userGroupRoleLineDal = new EfUserGroupRoleLineDal();

        private readonly ILanguageDal _languageDal = new EfLanguageDal();

        private readonly ISettingDal _settingDal = new EfSettingDal();

        #endregion
        #region Methods
        public AddModel<RoleLanguageLine> Add()
        {
            return new AddModel<RoleLanguageLine>
            {
                LanguageList = _languageDal.Filter(e => e.IsApproved)
            };
        }
        public void Add(AddModel<RoleLanguageLine> model)
        {
            var validator = new AddValidator(model);
            var roleLanguageLine = model.Item;
            var validationResults = validator.Validate();
            if (!validator.IsValid)
            {
                throw new ValidationException(Resources.InvalidEntityMessage)
                {
                    ValidationResult = validationResults
                };
            }
            var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;


            var role = new Role
            {
                CreateDate = DateTime.Now,
                CreatedBy = fikriKibarIdentity.UserId,
                UpdatedBy = fikriKibarIdentity.UserId,
                UpdateDate = DateTime.Now

            };

            var addedRole = _roleDal.Add(role);

            foreach (var languageId in model.SelectedLanguageIds)
            {
                roleLanguageLine.RoleId = addedRole.Id;
                roleLanguageLine.Role = null;
                roleLanguageLine.LanguageId = languageId;
                roleLanguageLine.RoleName = model.Item.RoleName;
                roleLanguageLine.RoleDescription = model.Item.RoleDescription;
                roleLanguageLine.CreatedBy = fikriKibarIdentity.UserId;
                roleLanguageLine.CreateDate = DateTime.Now;
                roleLanguageLine.UpdatedBy = fikriKibarIdentity.UserId;
                roleLanguageLine.UpdateDate = DateTime.Now;
                roleLanguageLine.PublishBeginDate = model.Item.PublishBeginDate;
                roleLanguageLine.PublishEndDate = model.Item.PublishEndDate;
                roleLanguageLine.DisplayOrder = addedRole.Id;
                roleLanguageLine.IsApproved = model.Item.IsApproved;
                _roleLanguageLineDal.Add(roleLanguageLine);
            }
        }
        public UpdateModel<RoleLanguageLine> Update(int id, string language)
        {
            var roleLanguageLine = _roleLanguageLineDal.Filter(e => e.RoleId == id && e.Language.LanguageCode == language).FirstOrDefault();
            if (roleLanguageLine == null) throw new NotFoundException();
            return new UpdateModel<RoleLanguageLine>
            {
                LanguageList = _languageDal.Filter(e => e.IsApproved),
                SelectedLanguageCode = language,
                ItemId = id,
                Item = roleLanguageLine
            };
        }
        public void Update(UpdateModel<RoleLanguageLine> model)
        {
            var validator = new UpdateValidator(model);
            var validationResults = validator.Validate();
            if (!validator.IsValid)
            {
                throw new ValidationException(Resources.InvalidEntityMessage)
                {
                    ValidationResult = validationResults
                };
            }
            var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;

            var role = _roleDal.GetById(model.ItemId);

            var roleHistory = new RoleHistory
            {
                RoleId = role.Id,
                CreateDate = role.CreateDate,
                CreatedBy = role.CreatedBy,
                UpdateDate = role.UpdateDate,
                UpdatedBy = role.UpdatedBy,
                IsDeleted = false
            };
            _roleHistoryDal.Add(roleHistory);


            role.UpdateDate = DateTime.Now;
            role.UpdatedBy = fikriKibarIdentity.UserId;
            var affectedRole = _roleDal.Update(role);

            var roleLanguageLine = _roleLanguageLineDal.Filter(e => e.RoleId == model.ItemId && e.Language.LanguageCode == model.SelectedLanguageCode).FirstOrDefault();

            if (roleLanguageLine == null)
            {
                roleLanguageLine = new RoleLanguageLine
                {
                    RoleId = affectedRole.Id,
                    Role = null,
                    LanguageId = _languageDal.GetByCode(model.SelectedLanguageCode).Id,
                    RoleName = model.Item.RoleName,
                    RoleDescription = model.Item.RoleDescription,
                    CreatedBy = fikriKibarIdentity.UserId,
                    CreateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    UpdateDate = DateTime.Now,
                    PublishBeginDate = model.Item.PublishBeginDate,
                    PublishEndDate = model.Item.PublishEndDate,
                    DisplayOrder = affectedRole.Id,
                    IsApproved = model.Item.IsApproved
                };
                _roleLanguageLineDal.Add(roleLanguageLine);

            }
            else
            {
                var roleLanguageLineHistory = new RoleLanguageLineHistory
                {
                    RoleLanguageLineId = roleLanguageLine.Id,
                    RoleId = roleLanguageLine.RoleId,
                    LanguageId = roleLanguageLine.LanguageId,
                    RoleName = roleLanguageLine.RoleName,
                    RoleDescription = roleLanguageLine.RoleDescription,
                    CreateDate = roleLanguageLine.CreateDate,
                    CreatedBy = role.CreatedBy,
                    UpdateDate = role.UpdateDate,
                    UpdatedBy = role.UpdatedBy,
                    PublishBeginDate = roleLanguageLine.PublishBeginDate,
                    PublishEndDate = roleLanguageLine.PublishEndDate,
                    DisplayOrder = roleLanguageLine.DisplayOrder,
                    IsApproved = roleLanguageLine.IsApproved,
                    IsDeleted = false
                };
                _roleLanguageLineHistoryDal.Add(roleLanguageLineHistory);

                roleLanguageLine.UpdateDate = DateTime.Now;
                roleLanguageLine.UpdatedBy = fikriKibarIdentity.UserId;
                roleLanguageLine.RoleName = model.Item.RoleName;
                roleLanguageLine.RoleDescription = model.Item.RoleDescription;
                roleLanguageLine.PublishBeginDate = model.Item.PublishBeginDate;
                roleLanguageLine.PublishEndDate = model.Item.PublishEndDate;
                roleLanguageLine.IsApproved = model.Item.IsApproved;

                _roleLanguageLineDal.Update(roleLanguageLine);
            }




        }
        public ListModel<RoleLanguageLine> GetList(string searchTerm, string languageCode, int status, int index, int size, string idsForSort, string idsForApprove, string idsForDelete)
        {
            var model = new ListModel<RoleLanguageLine>
            {
                Paging = new Paging(),
                ItemList = new List<RoleLanguageLine>(),
                LanguageList = _languageDal.Filter(e => e.IsApproved)
            };

            if (idsForDelete != null)
            {
                var ids = idsForDelete;
                ids = ids.Remove(ids.Length - 1);
                var idArray = ids.Split(',');
                var idList = idArray.Select(id => id.ConvertToInt()).ToList();
                DeleteSelected(idList, languageCode);

            }
            model.IdsForDelete = null;


            if (idsForApprove != null)
            {
                var ids = idsForApprove;
                ids = ids.Remove(ids.Length - 1);
                var idArray = ids.Split(',');
                var idList = idArray.Select(id => id.ConvertToInt()).ToList();
                ApproveSelected(idList, languageCode);
            }

            model.IdsForApprove = null;

            var sortHelper = new SortHelper<RoleLanguageLine>();
            sortHelper.OrderByDescending(t => t.DisplayOrder);

            model.Paging.CurrentPageSize = size;
            model.Paging.CurrentPage = index;
            model.SelectedStatus = status;

            if (status != -1)
            {
                var blStatus = status.ToString().ConvertToBoolean();
                model.Paging.TotalItemCount = _roleLanguageLineDal.GetTotalCount(e => e.RoleName.Contains(searchTerm) && e.Language.LanguageCode == languageCode && e.IsApproved == blStatus);
            }
            else
            {
                model.Paging.TotalItemCount = _roleLanguageLineDal.GetTotalCount(e => e.RoleName.Contains(searchTerm) && e.Language.LanguageCode == languageCode);
            }

            var pageSizeListSetting = _settingDal.GetValueByKey("PageSizeList");
            var pageSizeSettingValue = "10,25,50,100";
            if (pageSizeListSetting != null)
            {
                pageSizeSettingValue = pageSizeListSetting;
            }
            var pageSizeList = pageSizeSettingValue.Split(',').Select(t => new KeyValuePair<int, string>(t.ConvertToInt(), t)).ToList();

            pageSizeList.Insert(0, new KeyValuePair<int, string>(-1, "[" + Resources.All + "]"));
            model.Paging.PageSizeList = pageSizeList;


            if (status != -1)
            {
                var blStatus = status.ToString().ConvertToBoolean();
                model.ItemList = model.Paging.CurrentPageSize > 0 ? _roleLanguageLineDal.Filter(e => e.RoleName.Contains(searchTerm) && e.Language.LanguageCode == languageCode && e.IsApproved == blStatus, sortHelper, index, size) : _roleLanguageLineDal.Filter(e => e.RoleName.Contains(searchTerm) && e.Language.LanguageCode == languageCode && e.IsApproved == blStatus);
            }
            else
            {
                model.ItemList = model.Paging.CurrentPageSize > 0 ? _roleLanguageLineDal.Filter(e => e.RoleName.Contains(searchTerm) && e.Language.LanguageCode == languageCode, sortHelper, index, size) : _roleLanguageLineDal.Filter(e => e.RoleName.Contains(searchTerm) && e.Language.LanguageCode == languageCode);
            }


            if (idsForSort != null)
            {
                var ids = idsForSort;
                ids = ids.Remove(ids.Length - 1);
                var idArray = ids.Split(',');
                var idList = idArray.Select(id => id.ConvertToInt()).ToList();
                model.ItemList = SaveSort(idList, languageCode);
            }
            model.IdsForSort = null;

            model.Searched = searchTerm;
            model.SelectedLanguageCode = languageCode;

            model.Paging.CurrentPage = index;
            model.Paging.TotalPageCount = (int)Math.Ceiling((float)model.Paging.TotalItemCount / size);
            return model;
        }
           public void Delete(int id, string language)
        {
            var roleLanguageLine = _roleLanguageLineDal.Filter(e => e.Language.LanguageCode == language).FirstOrDefault(e => e.Role.Id == id);
            if (roleLanguageLine == null) return;
            var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;
            var roleLanguageLineHistory = new RoleLanguageLineHistory
            {
                RoleLanguageLineId = roleLanguageLine.Id,
                RoleId = roleLanguageLine.RoleId,
                LanguageId = roleLanguageLine.LanguageId,
                RoleName = roleLanguageLine.RoleName,
                RoleDescription = roleLanguageLine.RoleDescription,
                CreateDate = roleLanguageLine.CreateDate,
                CreatedBy = roleLanguageLine.CreatedBy,
                UpdateDate = DateTime.Now,
                UpdatedBy = fikriKibarIdentity.UserId,
                PublishBeginDate = roleLanguageLine.PublishBeginDate,
                PublishEndDate = roleLanguageLine.PublishEndDate,
                DisplayOrder = roleLanguageLine.DisplayOrder,
                IsApproved = roleLanguageLine.IsApproved,
                IsDeleted = true
            };
            _roleLanguageLineHistoryDal.Add(roleLanguageLineHistory);
            _roleLanguageLineDal.Delete(roleLanguageLine);

            if (_roleLanguageLineDal.Filter(e => e.RoleId == id).Any()) return;
            var role = _roleDal.GetById(id);
            if (role == null) return;
            var roleHistory = new RoleHistory
            {
                RoleId = role.Id,
                CreateDate = role.CreateDate,
                CreatedBy = role.CreatedBy,
                UpdateDate = DateTime.Now,
                UpdatedBy = fikriKibarIdentity.UserId,
                IsDeleted = true
            };
            _roleHistoryDal.Add(roleHistory);
            _roleDal.Delete(role);
        }
        public List<Role> GetRolesByUserId(int userId)
        {
            var list = new List<Role>();
            var userGroups = _userGroupUserLineDal.Filter(e => e.UserId == userId);
            if (userGroups == null) return list;
            foreach (var groupRoles in userGroups.Select(userGroup => _userGroupRoleLineDal.Filter(e => e.UserGroupId == userGroup.Id)).Where(groupRoles => groupRoles != null))
            {
                list.AddRange(groupRoles.Select(groupRole => groupRole.Role));
            }
            return list;
        }
        private List<RoleLanguageLine> SaveSort(IReadOnlyList<int> idList, string languageCode)
        {
            var returnedValue = new List<RoleLanguageLine>();
            for (var i = 0; i < idList.Count; i++)
            {
                var roleLanguageLine = _roleLanguageLineDal.Filter(e => e.Language.LanguageCode == languageCode).FirstOrDefault(e => e.Role.Id == idList[i]);

                if (roleLanguageLine == null) continue;
                var role = _roleDal.GetById(roleLanguageLine.Role.Id);
                var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;

                var roleHistory = new RoleHistory
                {
                    RoleId = role.Id,
                    CreateDate = role.CreateDate,
                    CreatedBy = role.CreatedBy,
                    UpdateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    IsDeleted = false
                };
                _roleHistoryDal.Add(roleHistory);


                role.UpdatedBy = fikriKibarIdentity.UserId;
                role.UpdateDate = DateTime.Now;
                _roleDal.Update(role);

                var roleLanguageLineHistory = new RoleLanguageLineHistory
                {
                    RoleLanguageLineId = roleLanguageLine.Id,
                    RoleId = roleLanguageLine.RoleId,
                    LanguageId = roleLanguageLine.LanguageId,
                    RoleName = roleLanguageLine.RoleName,
                    RoleDescription = roleLanguageLine.RoleDescription,
                    CreateDate = roleLanguageLine.CreateDate,
                    CreatedBy = roleLanguageLine.CreatedBy,
                    UpdateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    PublishBeginDate = roleLanguageLine.PublishBeginDate,
                    PublishEndDate = roleLanguageLine.PublishEndDate,
                    DisplayOrder = roleLanguageLine.DisplayOrder,
                    IsApproved = roleLanguageLine.IsApproved,
                    IsDeleted = false
                };
                _roleLanguageLineHistoryDal.Add(roleLanguageLineHistory);


                roleLanguageLine.DisplayOrder = i + 1;
                roleLanguageLine.UpdatedBy = fikriKibarIdentity.UserId;
                roleLanguageLine.UpdateDate = DateTime.Now;
                roleLanguageLine.Role = role;
                _roleLanguageLineDal.Update(roleLanguageLine);
                returnedValue.Add(roleLanguageLine);
            }
            return returnedValue;
        }
        private void ApproveSelected(IEnumerable<int> idList, string languageCode)
        {
            foreach (var id in idList)
            {
                var roleLanguageLine = _roleLanguageLineDal.Filter(e => e.Language.LanguageCode == languageCode).FirstOrDefault(e => e.Role.Id == id);
                if (roleLanguageLine == null) continue;
                var role = _roleDal.GetById(roleLanguageLine.Role.Id);
                var fikriKibarIdentity = (FikriKibarIdentity)Thread.CurrentPrincipal.Identity;
                var roleHistory = new RoleHistory
                {
                    RoleId = role.Id,
                    CreateDate = role.CreateDate,
                    CreatedBy = role.CreatedBy,
                    UpdateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    IsDeleted = false
                };
                _roleHistoryDal.Add(roleHistory);
                role.UpdatedBy = fikriKibarIdentity.UserId;
                role.UpdateDate = DateTime.Now;
                _roleDal.Update(role);

                var roleLanguageLineHistory = new RoleLanguageLineHistory
                {
                    RoleLanguageLineId = roleLanguageLine.Id,
                    RoleId = roleLanguageLine.RoleId,
                    LanguageId = roleLanguageLine.LanguageId,
                    RoleName = roleLanguageLine.RoleName,
                    RoleDescription = roleLanguageLine.RoleDescription,
                    CreateDate = roleLanguageLine.CreateDate,
                    CreatedBy = roleLanguageLine.CreatedBy,
                    UpdateDate = DateTime.Now,
                    UpdatedBy = fikriKibarIdentity.UserId,
                    PublishBeginDate = roleLanguageLine.PublishBeginDate,
                    PublishEndDate = roleLanguageLine.PublishEndDate,
                    DisplayOrder = roleLanguageLine.DisplayOrder,
                    IsApproved = roleLanguageLine.IsApproved,
                    IsDeleted = false
                };
                _roleLanguageLineHistoryDal.Add(roleLanguageLineHistory);


                roleLanguageLine.UpdatedBy = fikriKibarIdentity.UserId;
                roleLanguageLine.UpdateDate = DateTime.Now;
                roleLanguageLine.IsApproved = true;
                roleLanguageLine.Role = role;
                _roleLanguageLineDal.Update(roleLanguageLine);

            }
        }
        private void DeleteSelected(IEnumerable<int> idList, string languageCode)
        {
            foreach (var id in idList)
            {
                Delete(id, languageCode);
            }
        }
       
        #endregion
    }
}
